﻿using Microsoft.AspNetCore.Mvc;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;

namespace IOPerformanceTest.Controllers
{
    public class HomeController : Controller
    {
        private const long writeFileSize = 1024 * 1024 * 1024;
        private string writeFilePath = @"c:\";// AppContext.BaseDirectory;
        public async Task<IEnumerable<Performance>> SequenceWrite1K()
        {
            return await SequenceWrite(1024);
        }

        public async Task<IEnumerable<Performance>> SequenceWrite4K()
        {
            return await SequenceWrite(4096);
        }
        public async Task<IEnumerable<Performance>> SequenceWrite8K()
        {
            return await SequenceWrite(8192);
        }

        public async Task<IEnumerable<Performance>> AsyncSequenceWrite1K()
        {
            return await AsyncSequenceWrite(1024);
        }

        public async Task<IEnumerable<Performance>> AsyncSequenceWrite4K()
        {
            return await AsyncSequenceWrite(4096);
        }
        public async Task<IEnumerable<Performance>> AsyncSequenceWrite8K()
        {
            return await AsyncSequenceWrite(8192);
        }
        public async Task<IEnumerable<Performance>> MemoryMapSequenceWrite1K()
        {
            return await MemoryMapSequenceWrite(1024);
        }

        public async Task<IEnumerable<Performance>> MemoryMapSequenceWrite4K()
        {
            return await MemoryMapSequenceWrite(4096);
        }
        public async Task<IEnumerable<Performance>> MemoryMapSequenceWrite8K()
        {
            return await MemoryMapSequenceWrite(8192);
        }

        /// <summary>
        /// 内存映射文件顺序写入
        /// </summary>
        /// <returns></returns>
        private async Task<IEnumerable<Performance>> MemoryMapSequenceWrite(int buffSize)
        {
            if (Directory.Exists(writeFilePath) == false) Directory.CreateDirectory(writeFilePath);
            
            using (var memoryMappedFile = System.IO.MemoryMappedFiles.MemoryMappedFile.CreateFromFile(writeFilePath + this.ControllerContext.ActionDescriptor.ActionName, FileMode.Create,null,writeFileSize))
            {
                using (var write = memoryMappedFile.CreateViewAccessor())
                {
                    var buff = new byte[buffSize];
                    for(var i=0;i<buff.Length;i++)
                    {
                        buff[i] = 0xff;
                    }
                    List<Performance> ps = new List<Performance>();
                    var sw = new System.Diagnostics.Stopwatch();
                    sw.Start();
                    for (long i = 0; i < writeFileSize; i += buffSize)
                    {
                        if (i + buffSize < writeFileSize)
                        {
                            write.WriteArray(i, buff,0,buffSize);
                        }
                        else
                        {
                            write.WriteArray(i, buff, 0, (int)(writeFileSize - i));
                        }
                        var elapsedSeconds = (int)(sw.ElapsedMilliseconds / 1000 + 1);
                        if (ps.Count < elapsedSeconds)
                        {
                            ps.Add(new Performance()
                            {
                                ElapsedSeconds = elapsedSeconds,
                                WriteByteCount = buffSize
                            });
                        }
                        else
                        {
                            ps[elapsedSeconds - 1].WriteByteCount += buffSize;
                        }
                    }
                    ps.ForEach(r => r.WriteByteCount /= 1024 * 1024);
                    sw.Stop();
                    return ps;
                }
            }
        }

        /// <summary>
        /// 顺序写入
        /// </summary>
        /// <returns></returns>
        private async Task<IEnumerable<Performance>> SequenceWrite(int buffSize)
        {
            if (Directory.Exists(writeFilePath) == false) Directory.CreateDirectory(writeFilePath);

            using (var write = new FileStream(writeFilePath + this.ControllerContext.ActionDescriptor.ActionName, FileMode.Create, FileAccess.Write, FileShare.Read, buffSize, false))//此处的异步设置为true性能极差
            {
                var buff = new byte[buffSize];
                List<Performance> ps = new List<Performance>();
                var sw = new System.Diagnostics.Stopwatch();               
                sw.Start();
                for (long i = 0; i < writeFileSize; i += buffSize)
                {
                    if (i + buffSize < writeFileSize)
                    {
                        write.Write(buff, 0, buffSize);
                    }
                    else
                    {
                        write.Write(buff, 0, (int)(writeFileSize - i));
                    }
                    write.Flush();
                    var elapsedSeconds = (int)(sw.ElapsedMilliseconds / 1000 + 1);
                    if(ps.Count< elapsedSeconds)
                    {
                        ps.Add(new Performance()
                        {
                            ElapsedSeconds = elapsedSeconds,
                            WriteByteCount = buffSize
                        });
                    }
                    else
                    {
                        ps[elapsedSeconds - 1].WriteByteCount += buffSize;
                    }
                }
                ps.ForEach(r => r.WriteByteCount /= 1024 * 1024);
                sw.Stop();
                return ps;
            }
        }

        /// <summary>
        /// 顺序写入
        /// </summary>
        /// <returns></returns>
        private async Task<IEnumerable<Performance>> AsyncSequenceWrite(int buffSize)
        {
            if (Directory.Exists(writeFilePath) == false) Directory.CreateDirectory(writeFilePath);

            using (var write = new FileStream(writeFilePath + this.ControllerContext.ActionDescriptor.ActionName, FileMode.Create, FileAccess.Write,FileShare.Read, buffSize,false))//此处的异步设置为true性能极差
            {
                var buff = new byte[buffSize];
                List<Performance> ps = new List<Performance>();
                var sw = new System.Diagnostics.Stopwatch();
                sw.Start();
                for (long i = 0; i < writeFileSize; i += buffSize)
                {
                    if (i + buffSize < writeFileSize)
                    {
                        await write.WriteAsync(buff, 0, buffSize);
                    }
                    else
                    {
                       await write.WriteAsync(buff, 0, (int)(writeFileSize - i));
                    }
                    await write.FlushAsync();
                    var elapsedSeconds = (int)(sw.ElapsedMilliseconds / 1000 + 1);
                    if (ps.Count < elapsedSeconds)
                    {
                        ps.Add(new Performance()
                        {
                            ElapsedSeconds = elapsedSeconds,
                            WriteByteCount = buffSize
                        });
                    }
                    else
                    {
                        ps[elapsedSeconds - 1].WriteByteCount += buffSize;
                    }
                }
                ps.ForEach(r => r.WriteByteCount /= 1024 * 1024);
                sw.Stop();
                return ps;
            }
        }
    }
}
